package helplib

import (
	"container/list"
	"errors"
)

//Queue 自实现队列结构体
type Queue struct {
	buffer      list.List
	max         int
	autoReplace bool
}

//Push 入队列
//return error 队列已满
func (_this *Queue) Push(obj interface{}) error {
	if _this.IsFull() {
		if _this.autoReplace {
			_this.Pull()
			_this.buffer.PushBack(obj)
			return nil
		}
		return errors.New("队列已满，无法加入")
	}
	_this.buffer.PushBack(obj)
	return nil
}

//Pull 出队列
func (_this *Queue) Pull() interface{} {
	if _this.IsEmpty() {
		return nil
	}
	return _this.buffer.Remove(_this.buffer.Front())
}

//Current 查看当前队列头部元素，但不出队列
func (_this *Queue) Current() interface{} {
	if _this.IsEmpty() {
		return nil
	}
	return _this.buffer.Front().Value
}

//SetMaxLen 设置队列最大深度
//return error 队列深度设置需大于0
func (_this *Queue) SetMaxLen(max int) error {
	_this.max = max
	return nil
}

//SetAutoReplace 当队列满时是否自动滚动抛弃旧的
func (_this *Queue) SetAutoReplace(auto bool) {
	_this.autoReplace = true
}

//IsEmpty 判断队列是否为空
func (_this *Queue) IsEmpty() bool {
	return _this.buffer.Len() <= 0
}

//IsFull 判断队列是否已满
func (_this *Queue) IsFull() bool {
	return _this.max > 0 && _this.buffer.Len() >= _this.max
}

//QueueFirstLock 保持当前使用的元素不被替代的队列
type QueueFirstLock struct {
	Queue
}

//Push 入队列
//return error 队列已满
func (_this *QueueFirstLock) Push(obj interface{}) error {
	if _this.IsFull() {
		if _this.max > 1 {
			_this.buffer.Remove(_this.buffer.Front().Next())
			_this.buffer.PushBack(obj)
			return nil
		}
		return nil
	}
	_this.buffer.PushBack(obj)
	return nil
}

//IsSingle 队列元素是否有流动元素
func (_this *QueueFirstLock) IsSingle() bool {
	return _this.buffer.Len() == 1
}

//Len 队列元素是否有流动元素
func (_this *QueueFirstLock) Len() int {
	return _this.buffer.Len()
}
